package net.vinote.smart.platform.comm;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import java.util.Set;

/**
 * 提供了常用的字符串处理功能
 * 
 * @author zjw 2011-10-23
 */
public final class StringFunction {

	/**
	 * 获取当前时间
	 */
	public static String getTime() {
		DateFormat df = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
		String time = df.format(new Date());
		return time;
	}

	/**
	 * 是否为空白字符
	 */
	public static boolean isBlank(String... str) {
		if (str == null)
			return true;
		int length = str.length;
		for (int i = 0; i < length; i++) {
			if (str[i] == null || str[i].trim().equals(""))
				return true;
		}
		return false;
	}

	/**
	 * 若字符串为null,则转换为空字符串
	 */
	public static String nullToBlank(Object str) {
		return str == null ? "" : getValue(str.toString().trim(), "");
	}

	/**
	 * 若传入的参数val为null时,则返回default的值
	 * 
	 * @param val
	 * @param defualt
	 * @return
	 */
	public static String getValue(String val, String defualt) {
		if (val == null)
			val = defualt;
		return val;
	}

	/**
	 * 将请求参数转换为字符串 paramName1=paramValue1&paramName2=paramValue2
	 * 
	 * @param request
	 * @param exceptParamName
	 *            被排除的参数名
	 * @return
	 */
	public static String getParamterString(Map<String, String> requestMap,
			String... exceptParamName) {
		if (requestMap == null)
			return "";
		Set<String> paramterNameEnum = requestMap.keySet();
		int index = 0;
		StringBuilder sb = new StringBuilder();
		try {
			for (String paramName : paramterNameEnum) {
				if (exceptParamName != null) {
					for (String except : exceptParamName) {
						if (except.equals(paramName)) {
							continue;
						}
					}
				}
				if (++index > 1) {
					sb.append("&");
				}
				sb.append(paramName)
						.append("=")
						.append(URLEncoder.encode(requestMap.get(paramName),
								"utf-8"));
			}
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return sb.toString();
	}

	public static String replaceRevertAllHTML(String str) {
		return str.replace("<", "&lt;").replace(">", "&gt;");
	}

	final static char[] digits = { '0', '1', '2', '3', '4', '5', '6', '7', '8',
			'9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
			'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y',
			'z' };

	/**
	 * 以16进制 打印字节数组
	 * 
	 * @param bytes
	 *            byte[]
	 */
	public static String toHexString(byte[] bytes) {
		StringBuffer buffer = new StringBuffer(bytes.length);
		buffer.append("\r\n           0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f\r\n");
		int startIndex = 0;
		int column = 0;
		for (int i = 0; i < bytes.length; i++) {
			column = i % 16;
			switch (column) {
			case 0:
				startIndex = i;
				buffer.append(fixHexString(Integer.toHexString(i), 8)).append(
						": ");
				buffer.append(toHex(bytes[i]));
				buffer.append(" ");
				break;
			case 15:
				buffer.append(toHex(bytes[i]));
				buffer.append(" ; ");
				buffer.append(filterString(bytes, startIndex, column + 1));
				buffer.append("\r\n");
				break;
			default:
				buffer.append(toHex(bytes[i]));
				buffer.append(" ");
			}
		}
		if (column != 15) {
			for (int i = 0; i < (15 - column); i++) {
				buffer.append("   ");
			}
			buffer.append("; ").append(
					filterString(bytes, startIndex, column + 1));
			buffer.append("\r\n");
		}

		return buffer.toString();
	}

	/**
	 * 将hexStr格式化成length长度16进制数，并在后边加上h
	 * 
	 * @param hexStr
	 *            String
	 * @return String
	 */
	private static String fixHexString(String hexStr, int length) {
		if (hexStr == null || hexStr.length() == 0) {
			return "00000000h";
		} else {
			StringBuffer buf = new StringBuffer(length);
			int strLen = hexStr.length();
			for (int i = 0; i < length - strLen; i++) {
				buf.append("0");
			}
			buf.append(hexStr).append("h");
			return buf.toString();
		}
	}

	/**
	 * 将字节转换成16进制显示
	 * 
	 * @param b
	 *            byte
	 * @return String
	 */
	public static String toHex(byte b) {
		char[] buf = new char[2];
		for (int i = 0; i < 2; i++) {
			buf[1 - i] = digits[b & 0xF];
			b = (byte) (b >>> 4);
		}
		return new String(buf);
	}

	/**
	 * 过滤掉字节数组中0x0 - 0x1F的控制字符，生成字符串
	 * 
	 * @param bytes
	 *            byte[]
	 * @param offset
	 *            int
	 * @param count
	 *            int
	 * @return String
	 */
	private static String filterString(byte[] bytes, int offset, int count) {
		byte[] buffer = new byte[count];
		System.arraycopy(bytes, offset, buffer, 0, count);
		for (int i = 0; i < count; i++) {
			if (buffer[i] >= 0x0 && buffer[i] <= 0x1F) {
				buffer[i] = 0x2e;
			}
		}
		return new String(buffer);
	}

	/**
	 * Normalize a relative URI path that may have relative values ("/./",
	 * "/../", and so on ) it it. <strong>WARNING</strong> - This method is
	 * useful only for normalizing application-generated paths. It does not try
	 * to perform security checks for malicious input.
	 *
	 * @param path
	 *            Relative path to be normalized
	 */
	public static String normalize(String path) {
		return normalize(path, true);
	}

	/**
	 * Normalize a relative URI path that may have relative values ("/./",
	 * "/../", and so on ) it it. <strong>WARNING</strong> - This method is
	 * useful only for normalizing application-generated paths. It does not try
	 * to perform security checks for malicious input.
	 *
	 * @param path
	 *            Relative path to be normalized
	 * @param replaceBackSlash
	 *            Should '\\' be replaced with '/'
	 */
	public static String normalize(String path, boolean replaceBackSlash) {

		if (path == null)
			return null;

		// Create a place for the normalized path
		String normalized = path;

		if (replaceBackSlash && normalized.indexOf('\\') >= 0)
			normalized = normalized.replace('\\', '/');

		if (normalized.equals("/."))
			return "/";

		// Add a leading "/" if necessary
		if (!normalized.startsWith("/"))
			normalized = "/" + normalized;

		// Resolve occurrences of "//" in the normalized path
		while (true) {
			int index = normalized.indexOf("//");
			if (index < 0)
				break;
			normalized = normalized.substring(0, index)
					+ normalized.substring(index + 1);
		}

		// Resolve occurrences of "/./" in the normalized path
		while (true) {
			int index = normalized.indexOf("/./");
			if (index < 0)
				break;
			normalized = normalized.substring(0, index)
					+ normalized.substring(index + 2);
		}

		// Resolve occurrences of "/../" in the normalized path
		while (true) {
			int index = normalized.indexOf("/../");
			if (index < 0)
				break;
			if (index == 0)
				return (null); // Trying to go outside our context
			int index2 = normalized.lastIndexOf('/', index - 1);
			normalized = normalized.substring(0, index2)
					+ normalized.substring(index + 3);
		}

		// Return the normalized path that we have completed
		return (normalized);

	}
}
